까불이 코더 WPF 유튜브
- WPF로 PC카카오톡 로그인 화면을 만들어봐요
- C# 강의(24-8. CustomAttribute(사용자정의 어트리뷰트) 실전 활용 예제(Property))
WPF로 PC카카오톡 로그인 화면을 만들어봐요! [패키지 설치]
https://www.youtube.com/watch?v=eWSP4TOZjj4
WPF로 PC카카오톡 로그인 화면을 만들어봐요! [의존성 주입]
https://www.youtube.com/watch?v=DxibckiPDw0&t=316s
DesignPattern – Sigleton (싱글톤 패턴) [C#]
https://www.youtube.com/watch?v=GtkglhZkFhE
https://github.com/KaburiCoder/WPF-KabulTalk
1. WPF로 PC카카오톡 로그인 화면을 만들어봐요! [패키지 설치]
Manage Nuget Packages
1. CommunityToolkit.Mvvm 8.2.0 – Microsoft
2. Microsoft.Extensions.DependencyInjection 7.0.0 – Microsoft
3. FontAwesome6.Svg 2.5.1 – Codinion
4. Microsoft.Xaml.Behaviors.Wpf 1.1.39 – Microsoft
5. MySql.Data 8.0.33 – Oracle
WPF로 PC카카오톡 로그인 화면을 만들어봐요! [의존성 주입]
.NET Community Toolkit Introduction
구글에 검색 : Community toolkit
https://learn.microsoft.com/en-us/dotnet/communitytoolkit/introduction
https://learn.microsoft.com/en-us/dotnet/communitytoolkit/mvvm/ioc
Dependency Injection -> Inversion of control
의존성 주입 : 객체를 직접 생성하지 않고 서비스에 등록된 것을 불러오면 자동으로 생성해주는 방식
// App.xaml.cs
// App.xaml 에서 StartupUri="MainWindow.xaml" 부분을 삭제
using Microsoft.Extensions.DependencyInjection;
using MyTalk.Services;
using System;
using System.Windows;
namespace MyTalk
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
public App()
{
Services = ConfigureServices();
Startup += App_Startup;
}
private void App_Startup(object sender, StartupEventArgs e)
{
// 생성자에 매개변수를 입력하지 않아도 객체가 만들어짐.
var mainView = App.Current.Services.GetService<MainWindow>()!;
mainView.Show();
}
public new static App Current => (App)Application.Current;
public IServiceProvider Services { get; }
private static IServiceProvider ConfigureServices()
{
var services = new ServiceCollection();
// AddSingleton : 한번 생성이 되면 그 객체는 끝날 때까지 계속 사용
// 의존성을 주입하면 생성자에서 불러올 수 있다.
services.AddSingleton<ITestService, TestService>();
services.AddSingleton<MainWindow>();
return services.BuildServiceProvider();
}
}
}
// Services 폴더 생성
------------------------------------------
// ITestService.cs 인터페이스 파일 생성
public interface ITestService
{
string GetString();
}
------------------------------------------
// TestService.cs 클래스 파일 생성
public class TestService : ITestService
{
public string GetString()
{
return "마이톡입니다.";
}
}
public partial class MainWindow : Window
{
public MainWindow(ITestService testService)
{
InitializeComponent();
MessageBox.Show(testService.GetString());
}
}
DesignPattern – Sigleton (싱글톤 패턴) [C#]
싱글톤 패턴
싱글톤 패턴이란, 어떤 클래스가 최초 한 번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인 패턴입니다.
이후에는 미리 만들어진 메모리에 있는 인스턴스를 사용하기 때문에 메모리를 절약할 수 있습니다.
활용
1. 공통된 객체를 여러 개 생상하면 자원을 낭비할 때
2. 한번 생성한 객체를 여러 곳에서 공유해서 사용해야 할 때
3. 객체 생성에 대한 제한을 두고 싶을 때
namespace WpfApp1.Singletons
{
public class Logger
{
private readonly StringBuilder _logs = new StringBuilder();
private Logger() { }
private static readonly Lazy<Logger> _lazyLogger = new Lazy<Logger>(() => new Logger());
public static Logger Instance => _lazyLogger.Value;
public void Log(string message)
{
_logs.AppendLine($"{DateTime.Now}: {message}");
}
public string GetLogs()
{
return _logs.ToString(); }
}
}
<StackPanel>
<Button Click="btnCreateForm2_Click">폼2 생성</Button>
<Button Click="btnShowLogs_Click">로그 메시지 확인</Button>
</StackPanel>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Logger.Instance.Log("폼1이 생성되었습니다.");
}
private void btnCreateForm2_Click(object sender, RoutedEventArgs e)
{
var frm2 = new Form2();
frm2.Show();
}
private void btnShowLogs_Click(object sender, RoutedEventArgs e)
{
string logs = Logger.Instance.GetLogs();
MessageBox.Show(logs);
}
}
public partial class Form2 : Window
{
public Form2()
{
InitializeComponent();
Logger.Instance.Log("폼2가 생성되었습니다.");
Closed += Form2_Closed;
}
private void Form2_Closed(object? sender, EventArgs e)
{
Logger.Instance.Log("폼2가 닫혔습니다.");
}
}
2. C# 강의(24-8. CustomAttribute(사용자정의 어트리뷰트) 실전 활용 예제(Property))
https://www.youtube.com/watch?v=MnqJtJV-dLk
MainWindow.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
User user = new User()
{
Email = "Test@tEsT.Com",
Name = "CsHarpEXaMpLe",
Address = "셔울 종로구 세종대로"
};
Debug.WriteLine(user);
Debug.WriteLine("-----");
user.ApplyAttributes();
Debug.WriteLine(user);
}
}
Models/User.cs
using CustomAttributeExample.Attributes;
namespace CustomAttributeExample.Models
{
internal class User
{
[ToUpper]
public string Email { get; set; } = "";
[ToLower]
public string Name { get; set; } = "";
[Left(5)]
public string Address { get; set; } = "";
public override string? ToString()
{
return $"Email: {Email}\nName: {Name}\nAddress: {Address}";
}
}
}
Attributes/AttributeExtensions.cs
using System.Reflection;
namespace CustomAttributeExample.Attributes
{
internal static class AttributeExtensions
{
public static void ApplyAttributes(this object obj)
{
var properties = obj.GetType().GetProperties(); // 프로퍼티 가져오기
foreach (var property in properties)
{
var attributes = property.GetCustomAttributes().OfType<ITransformerAttribute<string>>(); //어트리뷰트 가져오기
foreach (var attr in attributes)
{
string? value = property.GetValue(obj) as string;
if (value != null) property.SetValue(obj, attr.Transform(value));
}
}
}
}
}
Attributes/ITransformerAttribute.cs
namespace CustomAttributeExample.Attributes
{
interface ITransformerAttribute<T>
{
T Transform(T value);
}
}
Attributes/LeftAttribute.cs
namespace CustomAttributeExample.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
internal class LeftAttribute : Attribute, ITransformerAttribute<string>
{
public LeftAttribute(int length)
{
Length = length;
}
public int Length { get; }
public string Transform(string value)
{
return value.Length > Length ? value.Substring(0, Length) : value;
}
}
}
Attributes/ToLowerAttribute.cs
namespace CustomAttributeExample.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
internal class ToLowerAttribute : Attribute, ITransformerAttribute<string>
{
public string Transform(string value)
{
return value.ToLower();
}
}
}
Attributes/ToUpperAttribute.cs
namespace CustomAttributeExample.Attributes
{
[AttributeUsage(AttributeTargets.Property)]
internal class ToUpperAttribute : Attribute, ITransformerAttribute<string>
{
public string Transform(string value)
{
return value.ToUpper();
}
}
}